package com.xlz.manager;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xlz.domain.AppInstance;
import com.xlz.util.LocalUtils;

/**
 * 分布式调度信息上下文.
 * @author 张蕾蕾
 * @date 2018 03 24
 */
public class DstContext {

	protected final Logger LOG = LoggerFactory.getLogger(getClass());
	
	//当前引用的唯一标识
	private String appNo;
	// 也就是实际分配的执行线程组，每一个AbstractTaskExecute算是一个线程组
	private Set<String> instanceUUIDs = new HashSet<String>();
	// 当前调度应用的唯一id
	private String instanceIp = LocalUtils.getLocalIP();
	// 当前调度应用的唯一id
	private String instanceId = instanceIp + "$" + UUID.randomUUID();
	
	private boolean isMaster = false;
	
	private long heartBeatRate;
	
	private Integer deadHeartCount = 5;
	
	public String getInstanceId() {
		return instanceId;
	}

	public boolean setInstanceUUIDs(List<AppInstance> currentList) {
		boolean diff = true;
		Set<String> currentSet = new HashSet<String>();
		if(currentList != null && !currentList.isEmpty()){
			//将内存中的应用（instances）和数据表中的对比，取差集，如果存在则表明有新的应用实例或者，有实例宕机
			for(AppInstance appInstance : currentList){
				currentSet.add(appInstance.getRegisterInstanceId());
			}
	        diff = diff(currentSet);
	        if(diff){
	        	//选主操作
				electLeader(currentList);
	        }
		}else{
			isMaster = false;
		}
        //存在差异更新缓存
        if(diff){
	        //将新的实例列表设置为本机最新
	        instanceUUIDs.clear();
	        instanceUUIDs.addAll(currentSet);
        }
        return diff;
	}
	
	/**
	 * 从当前注册的应用列表中id最小的选为master
	 * @param currentList
	 */
	private void electLeader(List<AppInstance> currentList){
		isMaster = false;
		Collections.sort(currentList,new Comparator<AppInstance>(){
			@Override
			public int compare(AppInstance o1, AppInstance o2) {
				return o2.getId().compareTo(o1.getId());
			}});
		if(currentList.get(0).getRegisterInstanceId().equals(this.getInstanceId()) ){
			isMaster = true;
		}
		LOG.error("当前机器是否为Master={}，当前id为{}",isMaster,this.getInstanceId());
	}
	
	/**
	 * 将数据库中注册应用列表和缓存中的列表进行diff，是否存在差异
	 * @param currentSet
	 * @return
	 */
	private boolean diff(Set<String> currentSet){
		Set<String> result = new HashSet<String>();
		//如果不存在本机ip则清空本机实例列表并且返回false，停止所有本机调度
		if(!currentSet.contains(this.getInstanceId())){
			instanceUUIDs.clear();
			return true;
		}
        result.clear();
        result.addAll(currentSet);
        result.removeAll(instanceUUIDs);
        
        if(result.isEmpty()){
        	result.clear();
            result.addAll(instanceUUIDs);
            result.removeAll(currentSet);
            LOG.debug("\t内存中当前应用实例缓存:{}",instanceUUIDs);
        }
        return !result.isEmpty();
	}

	public boolean isMaster() {
		return isMaster;
	}
	
	public void clearInstanceUUIDs(){
		instanceUUIDs.clear();
	}

	public Set<String> getInstanceUUIDs() {
		return instanceUUIDs;
	}

	public String getInstanceIp() {
		return instanceIp;
	}

	public Integer getDeadHeartCount() {
		return deadHeartCount;
	}

	public void setDeadHeartCount(Integer deadHeartCount) {
		this.deadHeartCount = deadHeartCount;
	}

	public String getAppNo() {
		return appNo;
	}

	public void setAppNo(String appNo) {
		this.appNo = appNo;
	}
	
	public long getHeartBeatRate() {
		return heartBeatRate;
	}

	public void setHeartBeatRate(long heartBeatRate) {
		this.heartBeatRate = heartBeatRate;
	}
}
